package com.gis.service.impl;


import cn.hutool.core.io.resource.ResourceUtil;
import com.gis.dto.*;
import com.gis.entity.StationData;
import com.gis.entity.WaterQualityData;
import com.gis.enums.QualityReportEnum;
import com.gis.exception.CustomException;
import com.gis.service.*;
import com.gis.utils.CommonUtil;
import com.gis.vo.BiologyReportVO;
import com.gis.vo.ReportVO;
import com.gis.vo.SedimentReportVO;
import com.gis.vo.WaterQualityReportVO;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.draw.LineSeparator;
import com.itextpdf.text.pdf.draw.VerticalPositionMark;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.*;
import java.util.List;

import static com.gis.maps.commonMap.getSeason;
import static com.gis.utils.CommonUtil.extractNumber;

@Slf4j
@Service
public class ReportExportServiceImpl implements ReportExportService {
    @Autowired
    private WaterQualityDataService waterQualityDataService;
    @Autowired
    private SedimentDataService sedimentDataService;
    @Autowired
    private IBiologyDataService biologyDataService;
    @Autowired
    private StationDataService stationDataService;



    /**
     * 生成水质报告
     * @param outputStream
     * @param year
     * @param season
     * @param screenshot
     */
    @Override
    public void generateWaterQualityReport(ByteArrayOutputStream outputStream, int year, String season, String screenshot) {
        try {
            Document document = new Document(PageSize.A4);
            PdfWriter.getInstance(document, outputStream);
            document.setMargins(70, 70, 70, 70); // 左、右、上、下边距
            document.open();
            /**
             * 中文字体
             * "STSong-Light"：宋体
             * "STSongStd-Light"：标准宋体
             */
            // 设置不同字体
            BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            BaseFont songFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            Font titleFont = new Font(songFont, 30, Font.BOLD, BaseColor.RED);  // 标题字体
            Font headerFont = new Font(baseFont, 15, Font.BOLD);              // 副标题字体
            Font normalFont = new Font(baseFont, 12, Font.NORMAL);             // 正文字体
            Font englishFont = FontFactory.getFont(FontFactory.TIMES_ROMAN, 12);

            // 添加标题
            Paragraph title = new Paragraph("小洋口海域海水水质评价", titleFont);
            title.setAlignment(Element.ALIGN_CENTER);
            title.setSpacingBefore(50);
            title.setSpacingAfter(50);
            document.add(title);
            document.add(new Paragraph("\n"));

            // 添加副标题
            Paragraph header = new Paragraph();
            header.setSpacingAfter(20);
            header.setTabSettings(new TabSettings(30));
            Chunk leftText = new Chunk("江苏省如东小洋口旅游度假区管理办公室", headerFont);
            header.add(leftText);
            Chunk tab = new Chunk(new VerticalPositionMark());
            header.add(tab);
            Chunk rightText = new Chunk(
                    String.format("%d年%s", year, season),
                    headerFont
            );
            header.add(rightText);
            document.add(header);
            document.add(new Paragraph("\n"));


            // 创建第一道横线
            LineSeparator line1 = new LineSeparator();
            line1.setLineColor(BaseColor.RED);
            line1.setLineWidth(1f);
            line1.setOffset(-2f); // 调整线条的位置
            // 创建第二道横线
            LineSeparator line2 = new LineSeparator();
            line2.setLineColor(BaseColor.RED);
            line2.setLineWidth(1f);
            line2.setOffset(-4f); // 调整线条的位置
            // 将横线添加到文档中
            document.add(line1);
            document.add(line2);


            // 添加水质评价情况
            Paragraph situation = new Paragraph("一、水质评价情况", headerFont);
            situation.setSpacingBefore(20);
            document.add(situation);
            document.add(new Paragraph("\n"));

            // 获取评价数据
            List<WaterQualityReportVO> reportData = getWaterQuality(year, season);
            //站点排序
            reportData.sort(Comparator.comparingInt(vo -> extractNumber(vo.getName())));

            // 添加统计信息
            Map<String, Double> statistics = calculateWaterStatistics(reportData);
            Paragraph stats = new Paragraph();
            stats.add(new Chunk(String.format(
                    "水质评价：第一类站位占 %.2f%%，第二类站位占 %.2f%%，第三类站位占 %.2f%%，第四类站位占 %.2f%%，劣四类站位占 %.2f%%；\n",
                    statistics.get("第一类"),
                    statistics.get("第二类"),
                    statistics.get("第三类"),
                    statistics.get("第四类"),
                    statistics.get("劣四类")
            ), normalFont));
            document.add(stats);
            document.add(new Paragraph("\n"));

            // 添加站点具体情况标题
            Paragraph stationTitle = new Paragraph("二、站点具体情况", headerFont);
            stationTitle.setSpacingBefore(10);
            document.add(stationTitle);
            document.add(new Paragraph("\n"));

            // 创建站点数据表格
            PdfPTable table = new PdfPTable(4);  // 4列
            table.setWidthPercentage(100);
            float[] columnWidths = {10f, 30f, 30f, 30f};
            table.setWidths(columnWidths);
            // 添加表头
            addTableHeader(table, normalFont, new String[]{"序号", "监测站位", "水质评价", "潮水状态"});
            // 添加数据行
            for (int i = 0; i < reportData.size(); i++) {
                WaterQualityReportVO data = reportData.get(i);
                addTableRow(table, normalFont, new String[]{
                        String.valueOf(i + 1),
                        data.getName(),
                        data.getLevel(),
                        data.getTideStatus(),
                });
            }
            document.add(table);





            if(screenshot!=null){
                // 处理Base64编码的图片
                String imageOnly = screenshot.split(",")[1];
                byte[] imageBytes = Base64.getDecoder().decode(imageOnly);
                // 添加水质评价情况
                document.newPage();
                Paragraph image = new Paragraph("三、水质评价专题图", headerFont);
                image.setSpacingBefore(20);
                document.add(image);
                document.add(new Paragraph("\n"));
                // 图片
                Image img = Image.getInstance(imageBytes);
                // 缩放
                float imageWidth = img.getWidth();
                float imageHeight = img.getHeight();
                float pageWidth = document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin();
                float scaleFactor = pageWidth / imageWidth;
                img.scaleAbsolute(imageWidth * scaleFactor, imageHeight * scaleFactor);
                img.setAlignment(Element.ALIGN_CENTER);
                document.add(img);
                // 图例
                byte[] resource = ResourceUtil.readBytes("image/appraise.png");
                Image img2 = Image.getInstance(resource);
                float imageWidth2 = img2.getWidth();
                float imageHeight2 = img2.getHeight();
                img2.scaleAbsolute((float) (imageWidth2 * 0.3), (float)(imageHeight2 * 0.3));
                // 调整图例图片的位置，使其与主图重叠，IText的坐标系是左下角为原点
                float mainImageLeftX = (document.getPageSize().getWidth() - imageWidth * scaleFactor) / 2;
                float scaledLegendWidth = (float)(imageWidth2 * 0.3);
                float offsetX = document.getPageSize().getWidth()-mainImageLeftX-scaledLegendWidth;
                float offsetY = document.getPageSize().getHeight() - imageHeight * scaleFactor - 125;
                img2.setAbsolutePosition(offsetX, offsetY);
                document.add(img2);


                // 添加水质评价情况
                Paragraph imageBottle = new Paragraph("海水水质评价专题图\n"+String.format("（%d年%s）", year, season), headerFont);
                imageBottle.setAlignment(Element.ALIGN_CENTER);
                imageBottle.setSpacingBefore(20);
                document.add(imageBottle);
                document.add(new Paragraph("\n"));
            }



            document.close();
        } catch (Exception e) {
            log.error("生成PDF报告失败", e);
            throw new CustomException("PDF生成失败");
        }
    }


    /**
     * 生成水质数据
     * @param year
     * @param season
     * @return
     */
    @Override
    public List<WaterQualityReportVO> getWaterQuality(int year, String season) {
        // 1.相关数据查询出来
        List<WaterQualityReportDTO> waterQualityReportDTOS = waterQualityDataService.getWaterQualityAvgByYearAndSeason(year,getSeason(season));
        // 2.各指标计算分类
        for(WaterQualityReportDTO waterQualityReportDTO : waterQualityReportDTOS){
            waterQualityReportDTO.setClassPh();
            waterQualityReportDTO.setClassDissolvedOxygen();
            waterQualityReportDTO.setClassCod();
            waterQualityReportDTO.setClassN();
            waterQualityReportDTO.setClassPo4();
            waterQualityReportDTO.setClassPetroleumClass();
            waterQualityReportDTO.setClassCopper();
            waterQualityReportDTO.setClassZinc();
            waterQualityReportDTO.setClassLead();
            waterQualityReportDTO.setClassCadmium();
            waterQualityReportDTO.setClassMercury();
            waterQualityReportDTO.setClassArsenic();
            waterQualityReportDTO.setClassChromium();
            waterQualityReportDTO.setClassSulfide();
            waterQualityReportDTO.setClassVoc();
        }
        // 3.综合评价 目前就是最低的分类就是综合评价分类
        List<WaterQualityReportVO> waterQualityReportVOS = new ArrayList<>();
        for(WaterQualityReportDTO waterQualityReportDTO : waterQualityReportDTOS){
            WaterQualityReportVO waterQualityReportVO = new WaterQualityReportVO();
            BeanUtils.copyProperties(waterQualityReportDTO, waterQualityReportVO);
            QualityReportEnum qualityReportEnum = QualityReportEnum.fromCode(waterQualityReportDTO.getComprehensiveClass());
            waterQualityReportDTO.print();
            waterQualityReportVO.setLevel(qualityReportEnum.getName());
            waterQualityReportVOS.add(waterQualityReportVO);
        }
        // 4.封装输出数据
        return waterQualityReportVOS;
    }


    /**
     * 生成沉积物报告
     *
     * @param outputStream
     * @param year
     * @param season
     * @param screenshot
     */
    @Override
    public void generateSedimentReport(ByteArrayOutputStream outputStream, int year, String season, String screenshot) {
        try {
            Document document = new Document(PageSize.A4);
            PdfWriter.getInstance(document, outputStream);
            document.setMargins(70, 70, 70, 70); // 左、右、上、下边距
            document.open();
            /**
             * 中文字体
             * "STSong-Light"：宋体
             * "STSongStd-Light"：标准宋体
             */
            // 设置不同字体
            BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            BaseFont songFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            Font titleFont = new Font(songFont, 30, Font.BOLD, BaseColor.RED);  // 标题字体
            Font headerFont = new Font(baseFont, 15, Font.BOLD);              // 副标题字体
            Font normalFont = new Font(baseFont, 12, Font.NORMAL);             // 正文字体
            Font englishFont = FontFactory.getFont(FontFactory.TIMES_ROMAN, 12);

            // 添加标题
            Paragraph title = new Paragraph("小洋口海域沉积物质量评价", titleFont);
            title.setAlignment(Element.ALIGN_CENTER);
            title.setSpacingBefore(50);
            title.setSpacingAfter(50);
            document.add(title);
            document.add(new Paragraph("\n"));

            // 添加副标题
            Paragraph header = new Paragraph();
            header.setSpacingAfter(20);
            header.setTabSettings(new TabSettings(30));
            Chunk leftText = new Chunk("江苏省如东小洋口旅游度假区管理办公室", headerFont);
            header.add(leftText);
            Chunk tab = new Chunk(new VerticalPositionMark());
            header.add(tab);
            Chunk rightText = new Chunk(
                    String.format("%d年%s", year, season),
                    headerFont
            );
            header.add(rightText);
            document.add(header);
            document.add(new Paragraph("\n"));


            // 创建第一道横线
            LineSeparator line1 = new LineSeparator();
            line1.setLineColor(BaseColor.RED);
            line1.setLineWidth(1f);
            line1.setOffset(-2f); // 调整线条的位置
            // 创建第二道横线
            LineSeparator line2 = new LineSeparator();
            line2.setLineColor(BaseColor.RED);
            line2.setLineWidth(1f);
            line2.setOffset(-4f); // 调整线条的位置
            // 将横线添加到文档中
            document.add(line1);
            document.add(line2);


            // 添加水质评价情况
            Paragraph situation = new Paragraph("一、沉积物质量评价情况", headerFont);
            situation.setSpacingBefore(20);
            document.add(situation);
            document.add(new Paragraph("\n"));

            // 获取评价数据
            List<SedimentReportVO> reportData = getSedimentQuality(year, season);
            //站点排序
            reportData.sort(Comparator.comparingInt(vo -> extractNumber(vo.getName())));

            // 添加统计信息
            Map<String, Double> statistics = calculateSedimentStatistics(reportData);
            Paragraph stats = new Paragraph();
            stats.add(new Chunk(String.format(
                    "沉积物质量评价：第一类站位占 %.2f%%，第二类站位占 %.2f%%，第三类站位占 %.2f%%；\n",
                    statistics.get("第一类"),
                    statistics.get("第二类"),
                    statistics.get("第三类")
            ), normalFont));
            document.add(stats);
            document.add(new Paragraph("\n"));

            // 添加站点具体情况标题
            Paragraph stationTitle = new Paragraph("二、站点具体情况", headerFont);
            stationTitle.setSpacingBefore(10);
            document.add(stationTitle);
            document.add(new Paragraph("\n"));

            // 创建站点数据表格
            PdfPTable table = new PdfPTable(3);  // 4列
            table.setWidthPercentage(70);
            float[] columnWidths = {10f, 30f, 30f};
            table.setWidths(columnWidths);
            // 添加表头
            addTableHeader(table, normalFont, new String[]{"序号", "监测站位", "沉积物评价"});
            // 添加数据行
            for (int i = 0; i < reportData.size(); i++) {
                SedimentReportVO data = reportData.get(i);
                addTableRow(table, normalFont, new String[]{
                        String.valueOf(i + 1),
                        data.getName(),
                        data.getLevel(),
                });
            }
            document.add(table);





            if(screenshot!=null){
                // 处理Base64编码的图片
                String imageOnly = screenshot.split(",")[1];
                byte[] imageBytes = Base64.getDecoder().decode(imageOnly);
                // 添加水质评价情况
                document.newPage();
                Paragraph image = new Paragraph("三、沉积物质量评价专题图", headerFont);
                image.setSpacingBefore(20);
                document.add(image);
                document.add(new Paragraph("\n"));
                // 图片
                Image img = Image.getInstance(imageBytes);
                float imageWidth = img.getWidth();
                float imageHeight = img.getHeight();
                float pageWidth = document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin();
                float scaleFactor = pageWidth / imageWidth;
                img.scaleAbsolute(imageWidth * scaleFactor, imageHeight * scaleFactor);
                img.setAlignment(Element.ALIGN_CENTER);
                document.add(img);
                // 图例
                byte[] resource = ResourceUtil.readBytes("image/appraise.png");
                Image img2 = Image.getInstance(resource);
                float imageWidth2 = img2.getWidth();
                float imageHeight2 = img2.getHeight();
                img2.scaleAbsolute((float) (imageWidth2 * 0.3), (float)(imageHeight2 * 0.3));
                // 调整图例图片的位置，使其与主图重叠，IText的坐标系是左下角为原点
                float mainImageLeftX = (document.getPageSize().getWidth() - imageWidth * scaleFactor) / 2;
                float scaledLegendWidth = (float)(imageWidth2 * 0.3);
                float offsetX = document.getPageSize().getWidth()-mainImageLeftX-scaledLegendWidth;
                float offsetY = document.getPageSize().getHeight() - imageHeight * scaleFactor - 125;
                img2.setAbsolutePosition(offsetX, offsetY);
                document.add(img2);
                // 添加水质评价情况
                Paragraph imageBottle = new Paragraph("沉积物质量评价专题图\n"+String.format("（%d年%s）", year, season), headerFont);
                imageBottle.setAlignment(Element.ALIGN_CENTER);
                imageBottle.setSpacingBefore(20);
                document.add(imageBottle);
                document.add(new Paragraph("\n"));
            }





            document.close();
        } catch (Exception e) {
            log.error("生成PDF报告失败", e);
            throw new CustomException("PDF生成失败");
        }
    }

    @Override
    public List<SedimentReportVO> getSedimentQuality(int year, String season) {
        // 1.相关数据查询出来
        List<SedimentReportDTO> sedimentReportDTOS = sedimentDataService.getSedimentQualityAvgByYearAndSeason(year, getSeason(season));
        // 2.各指标计算分类
        for(SedimentReportDTO sedimentReportDTO : sedimentReportDTOS){
            sedimentReportDTO.setClassMercury();
            sedimentReportDTO.setClassLead();
            sedimentReportDTO.setClassCadmium();
            sedimentReportDTO.setClassZinc();
            sedimentReportDTO.setClassArsenic();
            sedimentReportDTO.setClassCopper();
            sedimentReportDTO.setClassChromium();
            sedimentReportDTO.setClassPetroleumClass();
            sedimentReportDTO.setClassOc();
            sedimentReportDTO.setClassSulfide();
        }

        // 3.综合评价 目前就是最低的分类就是综合评价分类
        List<SedimentReportVO> sedimentReportVOS = new ArrayList<>();
        for(SedimentReportDTO sedimentReportDTO : sedimentReportDTOS){
            SedimentReportVO sedimentReportVO = new SedimentReportVO();
            sedimentReportVO.setId(sedimentReportDTO.getStationId());
            sedimentReportVO.setName(sedimentReportDTO.getName());
            sedimentReportVO.setLatitude(sedimentReportDTO.getLatitude());
            sedimentReportVO.setLongitude(sedimentReportDTO.getLongitude());
            QualityReportEnum sedimentQualityReportEnum = QualityReportEnum.fromCode(sedimentReportDTO.getComprehensiveClass());
            sedimentReportVO.setLevel(sedimentQualityReportEnum.getName());
            sedimentReportVOS.add(sedimentReportVO);
        }
        // 4.封装输出数据
        return sedimentReportVOS;
    }

    /**
     * 生物质量报告
     *
     * @param outputStream
     * @param year
     * @param season
     * @param screenshot
     */
    @Override
    public void generateBiologyReport(ByteArrayOutputStream outputStream, int year, String season, String screenshot) {
        try {
            Document document = new Document(PageSize.A4);
            PdfWriter.getInstance(document, outputStream);
            document.setMargins(70, 70, 70, 70); // 左、右、上、下边距
            document.open();
            /**
             * 中文字体
             * "STSong-Light"：宋体
             * "STSongStd-Light"：标准宋体
             */
            // 设置不同字体
            BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            BaseFont songFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            Font titleFont = new Font(songFont, 30, Font.BOLD, BaseColor.RED);  // 标题字体
            Font headerFont = new Font(baseFont, 15, Font.BOLD);              // 副标题字体
            Font normalFont = new Font(baseFont, 12, Font.NORMAL);             // 正文字体
            Font englishFont = FontFactory.getFont(FontFactory.TIMES_ROMAN, 12);

            // 添加标题
            Paragraph title = new Paragraph("小洋口海域生物质量评价", titleFont);
            title.setAlignment(Element.ALIGN_CENTER);
            title.setSpacingBefore(50);
            title.setSpacingAfter(50);
            document.add(title);
            document.add(new Paragraph("\n"));

            // 添加副标题
            Paragraph header = new Paragraph();
            header.setSpacingAfter(20);
            header.setTabSettings(new TabSettings(30));
            Chunk leftText = new Chunk("江苏省如东小洋口旅游度假区管理办公室", headerFont);
            header.add(leftText);
            Chunk tab = new Chunk(new VerticalPositionMark());
            header.add(tab);
            Chunk rightText = new Chunk(
                    String.format("%d年%s", year, season),
                    headerFont
            );
            header.add(rightText);
            document.add(header);
            document.add(new Paragraph("\n"));


            // 创建第一道横线
            LineSeparator line1 = new LineSeparator();
            line1.setLineColor(BaseColor.RED);
            line1.setLineWidth(1f);
            line1.setOffset(-2f); // 调整线条的位置
            // 创建第二道横线
            LineSeparator line2 = new LineSeparator();
            line2.setLineColor(BaseColor.RED);
            line2.setLineWidth(1f);
            line2.setOffset(-4f); // 调整线条的位置
            // 将横线添加到文档中
            document.add(line1);
            document.add(line2);


            // 添加水质评价情况
            Paragraph situation = new Paragraph("一、生物质量评价情况", headerFont);
            situation.setSpacingBefore(20);
            document.add(situation);
            document.add(new Paragraph("\n"));

            // 获取评价数据
            List<BiologyReportVO> reportData = getBiologyQuality(year, season);
            //站点排序
            reportData.sort(Comparator.comparingInt(vo -> extractNumber(vo.getName())));

            // 添加统计信息
            Map<String, Double> statistics = calculateBiologyStatistics(reportData);
            Paragraph stats = new Paragraph();
            stats.add(new Chunk(String.format(
                    "生物质量评价：第一类站位占 %.2f%%，第二类站位占 %.2f%%，第三类站位占 %.2f%%；\n",
                    statistics.get("第一类"),
                    statistics.get("第二类"),
                    statistics.get("第三类")
            ), normalFont));
            document.add(stats);
            document.add(new Paragraph("\n"));

            // 添加站点具体情况标题
            Paragraph stationTitle = new Paragraph("二、站点具体情况", headerFont);
            stationTitle.setSpacingBefore(10);
            document.add(stationTitle);
            document.add(new Paragraph("\n"));

            // 创建站点数据表格
            PdfPTable table = new PdfPTable(3);  // 4列
            table.setWidthPercentage(70);
            float[] columnWidths = {10f, 30f, 30f};
            table.setWidths(columnWidths);
            // 添加表头
            addTableHeader(table, normalFont, new String[]{"序号", "监测站位", "生物质量评价"});
            // 添加数据行
            for (int i = 0; i < reportData.size(); i++) {
                BiologyReportVO data = reportData.get(i);
                addTableRow(table, normalFont, new String[]{
                        String.valueOf(i + 1),
                        data.getName(),
                        data.getLevel(),
                });
            }
            document.add(table);





            if(screenshot!=null){
                // 处理Base64编码的图片
                String imageOnly = screenshot.split(",")[1];
                byte[] imageBytes = Base64.getDecoder().decode(imageOnly);
                // 添加水质评价情况
                document.newPage();
                Paragraph image = new Paragraph("三、生物质量评价专题图", headerFont);
                image.setSpacingBefore(20);
                document.add(image);
                document.add(new Paragraph("\n"));
                // 缩放
                Image img = Image.getInstance(imageBytes);
                float imageWidth = img.getWidth();
                float imageHeight = img.getHeight();
                float pageWidth = document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin();
                float scaleFactor = pageWidth / imageWidth;
                img.scaleAbsolute(imageWidth * scaleFactor, imageHeight * scaleFactor);
                img.setAlignment(Element.ALIGN_CENTER);
                document.add(img);
                // 图例
                byte[] resource = ResourceUtil.readBytes("image/appraise.png");
                Image img2 = Image.getInstance(resource);
                float imageWidth2 = img2.getWidth();
                float imageHeight2 = img2.getHeight();
                img2.scaleAbsolute((float) (imageWidth2 * 0.3), (float)(imageHeight2 * 0.3));
                // 调整图例图片的位置，使其与主图重叠，IText的坐标系是左下角为原点
                float mainImageLeftX = (document.getPageSize().getWidth() - imageWidth * scaleFactor) / 2;
                float scaledLegendWidth = (float)(imageWidth2 * 0.3);
                float offsetX = document.getPageSize().getWidth()-mainImageLeftX-scaledLegendWidth;
                float offsetY = document.getPageSize().getHeight() - imageHeight * scaleFactor - 125;
                img2.setAbsolutePosition(offsetX, offsetY);
                document.add(img2);
                // 添加水质评价情况
                Paragraph imageBottle = new Paragraph("生物质量评价专题图\n"+String.format("（%d年%s）", year, season), headerFont);
                imageBottle.setAlignment(Element.ALIGN_CENTER);
                imageBottle.setSpacingBefore(20);
                document.add(imageBottle);
                document.add(new Paragraph("\n"));
            }


            document.close();
        } catch (Exception e) {
            log.error("生成PDF报告失败", e);
            throw new CustomException("PDF生成失败");
        }
    }


    /**
     * 溢油报告
     *
     * @param outputStream
     * @param year
     * @param season
     * @param screenshot
     */
    @Override
    public void generateOilspillReport(ByteArrayOutputStream outputStream, int year, String season, String screenshot) {
        try {
            Document document = new Document(PageSize.A4);
            PdfWriter.getInstance(document, outputStream);
            document.setMargins(70, 70, 70, 70); // 左、右、上、下边距
            document.open();
            /**
             * 中文字体
             * "STSong-Light"：宋体
             * "STSongStd-Light"：标准宋体
             */
            // 设置不同字体
            BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            BaseFont songFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            Font titleFont = new Font(songFont, 30, Font.BOLD, BaseColor.RED);  // 标题字体
            Font headerFont = new Font(baseFont, 15, Font.BOLD);              // 副标题字体
            Font normalFont = new Font(baseFont, 12, Font.NORMAL);             // 正文字体
            Font englishFont = FontFactory.getFont(FontFactory.TIMES_ROMAN, 12);

            // 添加标题
            Paragraph title = new Paragraph("小洋口海域溢油风险预警", titleFont);
            title.setAlignment(Element.ALIGN_CENTER);
            title.setSpacingBefore(50);
            title.setSpacingAfter(50);
            document.add(title);
            document.add(new Paragraph("\n"));

            // 添加副标题
            Paragraph header = new Paragraph();
            header.setSpacingAfter(20);
            header.setTabSettings(new TabSettings(30));
            Chunk leftText = new Chunk("江苏省如东小洋口旅游度假区管理办公室", headerFont);
            header.add(leftText);
            Chunk tab = new Chunk(new VerticalPositionMark());
            header.add(tab);
            Chunk rightText = new Chunk(
                    String.format("%d年%s", year, season),
                    headerFont
            );
            header.add(rightText);
            document.add(header);
            document.add(new Paragraph("\n"));


            // 创建第一道横线
            LineSeparator line1 = new LineSeparator();
            line1.setLineColor(BaseColor.RED);
            line1.setLineWidth(1f);
            line1.setOffset(-2f); // 调整线条的位置
            // 创建第二道横线
            LineSeparator line2 = new LineSeparator();
            line2.setLineColor(BaseColor.RED);
            line2.setLineWidth(1f);
            line2.setOffset(-4f); // 调整线条的位置
            // 将横线添加到文档中
            document.add(line1);
            document.add(line2);


            // 添加水质评价情况
            Paragraph situation = new Paragraph("一、溢油风险预警情况", headerFont);
            situation.setSpacingBefore(20);
            document.add(situation);
            document.add(new Paragraph("\n"));

            // 获取评价数据
            List<ReportVO> reportVOS = new ArrayList<>();
            List<OilspillDTO> oilspillDTOS = getOilspill(year, getSeason(season));
            for (OilspillDTO oilspillDTO : oilspillDTOS){
                ReportVO reportVO = new ReportVO();
                StationData stationData = stationDataService.getById(oilspillDTO.getStationId());
                BeanUtils.copyProperties(stationData,reportVO);
                reportVO.setLevel(oilspillDTO.getResult().getName());
                reportVOS.add(reportVO);
            }
            //站点排序
            reportVOS.sort(Comparator.comparingInt(vo -> extractNumber(vo.getName())));

            // 添加统计信息
            Map<String, Double> statistics = calculateWarningStatistics(reportVOS);
            Paragraph stats = new Paragraph();
            stats.add(new Chunk(String.format(
                    "溢油预警情况：发生站位占 %.2f%%，不发生站位占 %.2f%%；\n",
                    statistics.get("发生"),
                    statistics.get("不发生")
            ), normalFont));
            document.add(stats);
            document.add(new Paragraph("\n"));

            // 添加站点具体情况标题
            Paragraph stationTitle = new Paragraph("二、站点具体情况", headerFont);
            stationTitle.setSpacingBefore(10);
            document.add(stationTitle);
            document.add(new Paragraph("\n"));

            // 创建站点数据表格
            PdfPTable table = new PdfPTable(3);  // 4列
            table.setWidthPercentage(70);
            float[] columnWidths = {10f, 30f, 30f};
            table.setWidths(columnWidths);
            // 添加表头
            addTableHeader(table, normalFont, new String[]{"序号", "监测站位", "溢油发生情况"});
            // 添加数据行
            for (int i = 0; i < reportVOS.size(); i++) {
                ReportVO data = reportVOS.get(i);
                addTableRow(table, normalFont, new String[]{
                        String.valueOf(i + 1),
                        data.getName(),
                        data.getLevel(),
                });
            }
            document.add(table);


            if(screenshot!=null){
                // 处理Base64编码的图片
                String imageOnly = screenshot.split(",")[1];
                byte[] imageBytes = Base64.getDecoder().decode(imageOnly);
                // 添加评价情况
                document.newPage();
                Paragraph image = new Paragraph("三、溢油风险预警专题图", headerFont);
                image.setSpacingBefore(20);
                document.add(image);
                document.add(new Paragraph("\n"));
                // 缩放
                Image img = Image.getInstance(imageBytes);
                float imageWidth = img.getWidth();
                float imageHeight = img.getHeight();
                float pageWidth = document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin();
                float scaleFactor = pageWidth / imageWidth;
                img.scaleAbsolute(imageWidth * scaleFactor, imageHeight * scaleFactor);
                img.setAlignment(Element.ALIGN_CENTER);
                document.add(img);
                // 图例
                byte[] resource = ResourceUtil.readBytes("image/warning.png");
                Image img2 = Image.getInstance(resource);
                float imageWidth2 = img2.getWidth();
                float imageHeight2 = img2.getHeight();
                img2.scaleAbsolute((float) (imageWidth2 * 0.3), (float)(imageHeight2 * 0.3));
                // 调整图例图片的位置，使其与主图重叠，IText的坐标系是左下角为原点
                float mainImageLeftX = (document.getPageSize().getWidth() - imageWidth * scaleFactor) / 2;
                float scaledLegendWidth = (float)(imageWidth2 * 0.3);
                float offsetX = document.getPageSize().getWidth()-mainImageLeftX-scaledLegendWidth;
                float offsetY = document.getPageSize().getHeight() - imageHeight * scaleFactor - 125;
                img2.setAbsolutePosition(offsetX, offsetY);
                document.add(img2);
                // 添加评价情况
                Paragraph imageBottle = new Paragraph("溢油风险预警专题图\n"+String.format("（%d年%s）", year, season), headerFont);
                imageBottle.setAlignment(Element.ALIGN_CENTER);
                imageBottle.setSpacingBefore(20);
                document.add(imageBottle);
                document.add(new Paragraph("\n"));
            }

            document.close();
        } catch (Exception e) {
            log.error("生成PDF报告失败", e);
            throw new CustomException("PDF生成失败");
        }
    }


    /**
     * 赤潮报告
     *
     * @param outputStream
     * @param year
     * @param season
     * @param screenshot
     */
    @Override
    public void generateRedtideReport(ByteArrayOutputStream outputStream, int year, String season, String screenshot) {
        try {
            Document document = new Document(PageSize.A4);
            PdfWriter.getInstance(document, outputStream);
            document.setMargins(70, 70, 70, 70); // 左、右、上、下边距
            document.open();
            /**
             * 中文字体
             * "STSong-Light"：宋体
             * "STSongStd-Light"：标准宋体
             */
            // 设置不同字体
            BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            BaseFont songFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            Font titleFont = new Font(songFont, 30, Font.BOLD, BaseColor.RED);  // 标题字体
            Font headerFont = new Font(baseFont, 15, Font.BOLD);              // 副标题字体
            Font normalFont = new Font(baseFont, 12, Font.NORMAL);             // 正文字体
            Font englishFont = FontFactory.getFont(FontFactory.TIMES_ROMAN, 12);

            // 添加标题
            Paragraph title = new Paragraph("小洋口海域赤潮灾害预警", titleFont);
            title.setAlignment(Element.ALIGN_CENTER);
            title.setSpacingBefore(50);
            title.setSpacingAfter(50);
            document.add(title);
            document.add(new Paragraph("\n"));

            // 添加副标题
            Paragraph header = new Paragraph();
            header.setSpacingAfter(20);
            header.setTabSettings(new TabSettings(30));
            Chunk leftText = new Chunk("江苏省如东小洋口旅游度假区管理办公室", headerFont);
            header.add(leftText);
            Chunk tab = new Chunk(new VerticalPositionMark());
            header.add(tab);
            Chunk rightText = new Chunk(
                    String.format("%d年%s", year, season),
                    headerFont
            );
            header.add(rightText);
            document.add(header);
            document.add(new Paragraph("\n"));


            // 创建第一道横线
            LineSeparator line1 = new LineSeparator();
            line1.setLineColor(BaseColor.RED);
            line1.setLineWidth(1f);
            line1.setOffset(-2f); // 调整线条的位置
            // 创建第二道横线
            LineSeparator line2 = new LineSeparator();
            line2.setLineColor(BaseColor.RED);
            line2.setLineWidth(1f);
            line2.setOffset(-4f); // 调整线条的位置
            // 将横线添加到文档中
            document.add(line1);
            document.add(line2);


            // 添加水质评价情况
            Paragraph situation = new Paragraph("一、赤潮灾害预警情况", headerFont);
            situation.setSpacingBefore(20);
            document.add(situation);
            document.add(new Paragraph("\n"));

            // 获取评价数据
            List<ReportVO> reportVOS = new ArrayList<>();
            List<RedtideDTO> redtideDTOS = getRedtide(year, getSeason(season));
            for (RedtideDTO redtideDTO : redtideDTOS){
                ReportVO reportVO = new ReportVO();
                StationData stationData = stationDataService.getById(redtideDTO.getStationId());
                BeanUtils.copyProperties(stationData,reportVO);
                reportVO.setLevel(redtideDTO.getResult().getName());
                reportVOS.add(reportVO);
            }
            //站点排序
            reportVOS.sort(Comparator.comparingInt(vo -> extractNumber(vo.getName())));

            // 添加统计信息
            Map<String, Double> statistics = calculateWarningStatistics(reportVOS);
            Paragraph stats = new Paragraph();
            stats.add(new Chunk(String.format(
                    "赤潮预警情况：发生站位占 %.2f%%，不发生站位占 %.2f%%；\n",
                    statistics.get("发生"),
                    statistics.get("不发生")
            ), normalFont));
            document.add(stats);
            document.add(new Paragraph("\n"));

            // 添加站点具体情况标题
            Paragraph stationTitle = new Paragraph("二、站点具体情况", headerFont);
            stationTitle.setSpacingBefore(10);
            document.add(stationTitle);
            document.add(new Paragraph("\n"));

            // 创建站点数据表格
            PdfPTable table = new PdfPTable(3);  // 4列
            table.setWidthPercentage(70);
            float[] columnWidths = {10f, 30f, 30f};
            table.setWidths(columnWidths);
            // 添加表头
            addTableHeader(table, normalFont, new String[]{"序号", "监测站位", "赤潮发生情况"});
            // 添加数据行
            for (int i = 0; i < reportVOS.size(); i++) {
                ReportVO data = reportVOS.get(i);
                addTableRow(table, normalFont, new String[]{
                        String.valueOf(i + 1),
                        data.getName(),
                        data.getLevel(),
                });
            }
            document.add(table);


            if(screenshot!=null){
                // 处理Base64编码的图片
                String imageOnly = screenshot.split(",")[1];
                byte[] imageBytes = Base64.getDecoder().decode(imageOnly);
                // 添加评价情况
                document.newPage();
                Paragraph image = new Paragraph("三、赤潮灾害预警专题图", headerFont);
                image.setSpacingBefore(20);
                document.add(image);
                document.add(new Paragraph("\n"));
                // 缩放
                Image img = Image.getInstance(imageBytes);
                float imageWidth = img.getWidth();
                float imageHeight = img.getHeight();
                float pageWidth = document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin();
                float scaleFactor = pageWidth / imageWidth;
                img.scaleAbsolute(imageWidth * scaleFactor, imageHeight * scaleFactor);
                img.setAlignment(Element.ALIGN_CENTER);
                document.add(img);
                // 图例
                byte[] resource = ResourceUtil.readBytes("image/warning.png");
                Image img2 = Image.getInstance(resource);
                float imageWidth2 = img2.getWidth();
                float imageHeight2 = img2.getHeight();
                img2.scaleAbsolute((float) (imageWidth2 * 0.3), (float)(imageHeight2 * 0.3));
                // 调整图例图片的位置，使其与主图重叠，IText的坐标系是左下角为原点
                float mainImageLeftX = (document.getPageSize().getWidth() - imageWidth * scaleFactor) / 2;
                float scaledLegendWidth = (float)(imageWidth2 * 0.3);
                float offsetX = document.getPageSize().getWidth()-mainImageLeftX-scaledLegendWidth;
                float offsetY = document.getPageSize().getHeight() - imageHeight * scaleFactor - 125;
                img2.setAbsolutePosition(offsetX, offsetY);
                document.add(img2);
                // 添加评价情况
                Paragraph imageBottle = new Paragraph("赤潮灾害预警专题图\n"+String.format("（%d年%s）", year, season), headerFont);
                imageBottle.setAlignment(Element.ALIGN_CENTER);
                imageBottle.setSpacingBefore(20);
                document.add(imageBottle);
                document.add(new Paragraph("\n"));
            }

            document.close();
        } catch (Exception e) {
            log.error("生成PDF报告失败", e);
            throw new CustomException("PDF生成失败");
        }
    }

    /**
     * 获取赤潮数据
     *
     * @param year
     * @param season
     * @return
     */
    @Override
    public List<RedtideDTO> getRedtide(int year, String season) {
        // 1.相关数据查询出来
        List<WaterQualityData> waterQualityDataList = waterQualityDataService.getRedtideDataByTime(year, season);
        // 2.整合放到一个评价dto里 要先确定站点都有这些数据 再保留
//        Map<Integer, WaterQualityData> waterQualityMap = waterQualityData.stream()
//                .collect(Collectors.toMap(WaterQualityData::getStationId, data -> data));
//        Map<Integer, SedimentData> sedimentMap = sedimentData.stream()
//                .collect(Collectors.toMap(SedimentData::getStationId, data -> data));
//        Map<Integer, BiologyData> biologyMap = biologyData.stream()
//                .collect(Collectors.toMap(BiologyData::getStationId, data -> data));
//        // Set 找出三个 Map 中都存在的 stationId
//        Set<Integer> commonStationIds = waterQualityMap.keySet();
//        commonStationIds.retainAll(sedimentMap.keySet());
//        commonStationIds.retainAll(biologyMap.keySet());
//        List<RedtideDTO> redtideDTOS = new ArrayList<>();
//        for (int stationId : commonStationIds) {
//            WaterQualityData waterQuality = waterQualityMap.get(stationId);
//            SedimentData sediment = sedimentMap.get(stationId);
//            BiologyData biology = biologyMap.get(stationId);
//
//            RedtideDTO redtideDTO = new RedtideDTO();
//            redtideDTO.setStationId(stationId);
//            redtideDTOS.add(redtideDTO);
//        }

        List<RedtideDTO> redtideDTOS = new ArrayList<>();
        for (WaterQualityData waterQualityData : waterQualityDataList){
            RedtideDTO redtideDTO = new RedtideDTO();
            BeanUtils.copyProperties(waterQualityData, redtideDTO);
            redtideDTOS.add(redtideDTO);
        }
        if(redtideDTOS.isEmpty()){
            throw new CustomException("赤潮数据为空");
        }
        return redtideDTOS;
    }



    /**
     * 获取溢油数据
     *
     * @param year
     * @param season
     * @return
     */
    @Override
    public List<OilspillDTO> getOilspill(int year, String season) {
        List<WaterQualityData> waterQualityDataList = waterQualityDataService.getOilspillDataByTime(year, season);
        List<OilspillDTO> oilspillDTOS = new ArrayList<>();
        for (WaterQualityData waterQualityData : waterQualityDataList){
            OilspillDTO oilspillDTO = new OilspillDTO();
            BeanUtils.copyProperties(waterQualityData, oilspillDTO);
            oilspillDTOS.add(oilspillDTO);
        }
        if(oilspillDTOS.isEmpty()){
            throw new CustomException("溢油数据为空");
        }
        return oilspillDTOS;
    }


    /**
     * 生物质量数据
     * @param year
     * @param season
     * @return
     */
    @Override
    public List<BiologyReportVO> getBiologyQuality(int year, String season) {
        // 1.相关数据查询出来
        List<BiologyReportDTO> biologyReportDTOS = biologyDataService.getBiologyQualityAvgByYearAndSeason(year, getSeason(season));
        // 2.各指标计算分类
        for(BiologyReportDTO biologyReportDTO : biologyReportDTOS){
            biologyReportDTO.setClassMercury();
            biologyReportDTO.setClassCadmium();
            biologyReportDTO.setClassLead();
            biologyReportDTO.setClassChromium();
            biologyReportDTO.setClassArsenic();
            biologyReportDTO.setClassCopper();
            biologyReportDTO.setClassZinc();
            biologyReportDTO.setClassTph();
        }

        // 3.综合评价 目前就是最低的分类就是综合评价分类
        List<BiologyReportVO> biologyReportVOS = new ArrayList<>();
        for(BiologyReportDTO biologyReportDTO : biologyReportDTOS){
            BiologyReportVO biologyReportVO = new BiologyReportVO();
            biologyReportVO.setId(biologyReportDTO.getStationId());
            biologyReportVO.setName(biologyReportDTO.getName());
            biologyReportVO.setLatitude(biologyReportDTO.getLatitude());
            biologyReportVO.setLongitude(biologyReportDTO.getLongitude());
            QualityReportEnum sedimentQualityReportEnum = QualityReportEnum.fromCode(biologyReportDTO.getComprehensiveClass());
            biologyReportVO.setLevel(sedimentQualityReportEnum.getName());
            biologyReportVOS.add(biologyReportVO);
        }
        // 4.封装输出数据
        return biologyReportVOS;
    }




    /**
     * 表格操作
     * @param table
     * @param font
     * @param headers
     */
    private void addTableHeader(PdfPTable table, Font font, String[] headers) {
        for (String header : headers) {
            PdfPCell cell = new PdfPCell(new Phrase(header, font));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            cell.setPadding(5);
            table.addCell(cell);
        }
    }
    private void addTableRow(PdfPTable table, Font font, String[] rowData) {
        for (String data : rowData) {
            PdfPCell cell = new PdfPCell(new Phrase(data, font));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            cell.setPadding(5);
            table.addCell(cell);
        }
    }

    /**
     * 计算水质统计数据
     * @param data
     * @return
     */
    private Map<String, Double> calculateWaterStatistics(List<WaterQualityReportVO> data) {
        Map<String, Double> stats = new HashMap<>();
        int total = data.size();

        long first = data.stream().filter(d -> "第一类".equals(d.getLevel())).count();
        long second = data.stream().filter(d -> "第二类".equals(d.getLevel())).count();
        long third = data.stream().filter(d -> "第三类".equals(d.getLevel())).count();
        long fourth = data.stream().filter(d -> "第四类".equals(d.getLevel())).count();
        long fifth = data.stream().filter(d -> "劣四类".equals(d.getLevel())).count();

        stats.put("第一类", first * 100.0 / total);
        stats.put("第二类", second * 100.0 / total);
        stats.put("第三类", third * 100.0 / total);
        stats.put("第四类", fourth * 100.0 / total);
        stats.put("劣四类", fifth * 100.0 / total);

        return stats;
    }

    /**
     * 计算沉积物统计数据
     * @param data
     * @return
     */
    private Map<String, Double> calculateSedimentStatistics(List<SedimentReportVO> data) {
        Map<String, Double> stats = new HashMap<>();
        int total = data.size();

        long first = data.stream().filter(d -> "第一类".equals(d.getLevel())).count();
        long second = data.stream().filter(d -> "第二类".equals(d.getLevel())).count();
        long third = data.stream().filter(d -> "第三类".equals(d.getLevel())).count();

        stats.put("第一类", first * 100.0 / total);
        stats.put("第二类", second * 100.0 / total);
        stats.put("第三类", third * 100.0 / total);

        return stats;
    }
    /**
     * 计算生物质量统计数据
     * @param data
     * @return
     */
    private Map<String, Double> calculateBiologyStatistics(List<BiologyReportVO> data) {
        Map<String, Double> stats = new HashMap<>();
        int total = data.size();

        long first = data.stream().filter(d -> "第一类".equals(d.getLevel())).count();
        long second = data.stream().filter(d -> "第二类".equals(d.getLevel())).count();
        long third = data.stream().filter(d -> "第三类".equals(d.getLevel())).count();

        stats.put("第一类", first * 100.0 / total);
        stats.put("第二类", second * 100.0 / total);
        stats.put("第三类", third * 100.0 / total);

        return stats;
    }


    private Map<String, Double> calculateWarningStatistics(List<ReportVO> data) {
        Map<String, Double> stats = new HashMap<>();
        int total = data.size();

        long first = data.stream().filter(d -> "发生".equals(d.getLevel())).count();
        long second = data.stream().filter(d -> "不发生".equals(d.getLevel())).count();

        stats.put("发生", first * 100.0 / total);
        stats.put("不发生", second * 100.0 / total);

        return stats;
    }



}
